/*
 * UART.c
 *
 *  Created on: 09-02-2012
 *      Author: Mati
 */
#include "UART.h"

extern xSemaphoreHandle xUartReceivedSem;

//ProtocolMarker *pPmarker = &PMarker;

// ========================= UART1 - FTDI ==========================================
__INLINE void UART1_Config(int Baudrate)
{
    volatile uint64_t DLest;
    uint32_t pclkdiv, pclk;
    const uint8_t MulVal=2;
    const uint8_t DivAddVal=1;
    const int SystemFrequency = 100000000UL;

    LPC_SC->PCONP |=  (1U<<4);									// Turn on power to UART1
    LPC_PINCON->PINSEL4 |= (LPC_PINCON->PINSEL4 & ~0xf)|		//ensure being cleared
    					   (2U << 0)|							//P0.0 = TXD1
    					   (2U << 2);							//P0.1 = RXD1

    LPC_UART1->LCR =  (3U<<0)|      	//8 bit
    				  (0U<<2)|			//1 stop bit
    				  (0U<<3)|			//no parity
    				  (1U<<7);			//DLAB=1

    LPC_UART1->FDR = (MulVal<<4) | (DivAddVal<<0);			//MulVal=2, DivAddVal=1

    pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03; //select PCLK_UART1 in PCLKSEL0

    // PCLK is 01 in
    switch ( pclkdiv ){
		case 0x00:
		default:
			pclk = SystemFrequency/4;
		break;
		case 0x01:
			pclk = SystemFrequency;
		break;
		case 0x02:
			pclk = SystemFrequency/2;
		break;
		case 0x03:
			pclk = SystemFrequency/8;
		break;
	}

    DLest = (pclk>>4)/((Baudrate*(MulVal+DivAddVal))/MulVal);   	//Set baud rate
    LPC_UART1->DLM = DLest>>8;			//BaudRateClock Lower 8 bits
    LPC_UART1->DLL = DLest%256;

    //FIFO
    LPC_UART1->FCR = (1U<<0);//|      	// FIFO Enable
//    				 (0x01U<<6);	// 4 bajty - RX Trigger Level; 0->1znak, 1->4, 2->8, 3->14;


    LPC_UART1->LCR = (LPC_UART1->LCR) & (~0x80); //DLAB=0 to use TER
    LPC_UART1->IER = (1<<0);	//RBR Interrupt enabled (Receive Buffer)
    //LPC_UART1->TER = (1<<7);	//Transmit Enable = 1
    NVIC_EnableIRQ(UART1_IRQn);
    NVIC_SetPriority(UART1_IRQn,7);
}

__INLINE void  UART1_PrintChar (uint8_t ch)		//byl uint
{
   while (!(LPC_UART1->LSR & 0x20));
   LPC_UART1->THR  = ch;
}

__INLINE void UART1_PrintStr (uint8_t * str)
{
   while ((*str) != 0) {
      if (*str == '\n') {
         UART1_PrintChar(*str++);
         UART1_PrintChar('\r');
      } else {
         UART1_PrintChar(*str++);
      }
   }
}

__INLINE void UART1_SendDibyte(uint16_t dibyte){
	UART1_PrintChar((dibyte & 0xff00)>>8);
	UART1_PrintChar((dibyte & 0x00ff));
}

__INLINE void UART1_RxFIFO_Reset(void){
	LPC_UART1->FCR |=  (1U<<1);
}
void  UART_Sendchar(char c){
   while (!(LPC_UART1->LSR & 0x20));	/* Block until tx empty */
   LPC_UART1->THR  = c;
}
char UART_Getchar(void){
	char c;
	while(!(LPC_UART1->LSR & 0x01));	/* Block until rx not empty */
	c = LPC_UART1->RBR;					/* Read receiver buffer register */
	return c;
}
uint8_t UART1_GetByte(void){
	uint8_t _byte = 0;
	char c;
	while(!(LPC_UART1->LSR & 0x01));		/* Block until rx not empty */
	_byte = LPC_UART1->RBR;					/* Read receiver buffer register */
	return _byte;
}
uint16_t UART1_GetValue(void){
	uint16_t val = 0;
	val  = ( (LPC_UART1->RBR<<8) & 0xFF00);
	val |= ( (LPC_UART1->RBR)    & 0x00FF);
	return val;
}

void UART1_IRQHandler()
{
	uint8_t stat;
	stat = (LPC_UART1->IIR & 0x0f);
	LPC_UART1->IER &= ~(1U<<0);								// wylacz przerwania od RBR Interrupt enabled (Receive Buffer)

	uint8_t recByte;
	recByte = UART1_GetByte();

	portBASE_TYPE xCheckWhatReceived = pdFALSE; //nie chcemy od razu budzic zadania
	//printf("odebralem bajt %X\n\r",recByte);
	LED_Toggle(1<<6);
	if( 0x4==(stat&0x4) && ((PMarker.SOF) == recByte))															// jezeli takie przerwanie: Receive Data Available (RDA)
	{
		//UART1_PrintStr("Wysylam semafor\n");
		NVIC_DisableIRQ(TIMER1_IRQn);
		xSemaphoreGiveFromISR( xUartReceivedSem, &xCheckWhatReceived );
		if( pdTRUE == xCheckWhatReceived)
		{
			portYIELD();
		}
	}
	return;

}
